#include "fichier.h"
#define TAILLE_ARBO_MAX 2048
#define TAILLE_FICH_MAX 64
#define TAILLE_DOSS_MAX TAILLE_ARBO_MAX-TAILLE_FICH_MAX

#define STR_VALUE(val) #val
#define STR(name) STR_VALUE(name)


#define PATH_LEN 256
#define MD5_LEN 32

/**
 *
 */
int fichier_liste ( const char * dossier , int niveau){
    DIR * dir;
    char doss[TAILLE_DOSS_MAX +1];
    char arbo[TAILLE_ARBO_MAX +1];

    char md5[MD5_LEN + 1];

    struct dirent * contenus;

    /* le nom de dossier est il trop grand? */
    if( TAILLE_DOSS_MAX < strlen(dossier) )
    {
        return 47;
    }

    strcpy(doss, dossier);

    /* ouverture du dossier */
    if ( NULL == (dir = opendir(doss))){
        perror( "erreur d'ouverture du dossier %s !");
        return 1 ;
    }

    /* il y a t'il '/' a la fin? */
    if ( doss[strlen(doss)-1] != '/' )
    {
        if ( TAILLE_DOSS_MAX  < strlen(doss) )
            return 47;
        doss[strlen(doss)+1] = '\0';
        doss[strlen(doss)] = '/';
    }
    printf("%s\n", doss);


    while( (contenus = readdir(dir))){
        if ( ( strncmp(contenus->d_name, ".", 1) != 0 ) && ( strncmp(contenus->d_name, "..", 2 ) != 0 ) ){



            strcpy(arbo, doss);
            if ( TAILLE_ARBO_MAX == strlen(arbo) )
                return 2001;


            strcat(arbo,(char *) (contenus->d_name));
            espace(niveau);

            fichier_MD5(arbo, md5);

            printf("%c %s %s %s\n", fichier_type(arbo ),arbo, fichier_LastMod(arbo), md5 );

            if('d' == fichier_type(arbo)){
                fichier_liste(arbo , niveau +1);
            }


        }
    }
    closedir(dir);
    free(contenus );
    return 0;
}


/**
 *
 */
char fichier_type( const char * fichier){
    struct stat infos;

    if ( -1 == stat(fichier, &infos)){
        perror("erreur d'ouverture des caracteristiques du fichier");
        return 'e';
    }
    if ( S_ISREG( infos.st_mode) )
        return 'f';

    if ( S_ISFIFO( infos.st_mode ) )
        return 't';

    if ( S_ISCHR( infos.st_mode ) )
        return 'c';

    if ( S_ISBLK( infos.st_mode ) )
        return 'b';

    if ( S_ISDIR( infos.st_mode ) )
        return 'd';

    if ( S_ISLNK ( infos.st_mode ) )
        return 'l';

    /*if ( S_ISSOCK ( infos.st_mode ) )
      return 's';*/

    return 'e';
}

time_t fichier_date( const char * fichier){
    struct stat infos;

    if ( -1 == stat(fichier, &infos)){
        perror("erreur d'ouverture des caracteristiques du fichier");
        return 0;
    }

    return infos.st_mtime;
}

void espace(int nb){
    int i;
    if (nb< 0)
        printf(" ");
    else
        for(i=0; i< nb; ++i)
            printf(" ");
}

char* fichier_LastMod(char *path) {
    struct stat attr;
    stat(path, &attr);
    return ctime(&attr.st_mtime);
}


int fichier_MD5(char *file_name, char *md5_sum)
{
    #define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null"
    char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)];
    sprintf(cmd, MD5SUM_CMD_FMT, file_name);
    #undef MD5SUM_CMD_FMT

    FILE *p = popen(cmd, "r");
    if (p == NULL) return 0;

    int i, ch;
    for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) {
        *md5_sum++ = ch;
    }

    *md5_sum = '\0';
    pclose(p);
    return i == MD5_LEN;
}

